package me.longerian.server.utils;

import java.security.SecureRandom;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;


public class DESUtil {
	
	/**
	 * not compatible with CryptoJS
	 * @param datasource
	 * @param password
	 * @return
	 */
	public static byte[] encrypt(byte[] datasource, String password) {
		try {
			SecureRandom random = new SecureRandom();
			DESKeySpec desKey = new DESKeySpec(password.getBytes());
			// 创建一个密匙工厂，然后用它把DESKeySpec转换成
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey securekey = keyFactory.generateSecret(desKey);
			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance("DES");
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
			// 现在，获取数据并加密
			// 正式执行加密操作
			return cipher.doFinal(datasource);
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * not compatible with CryptoJS
	 * @param src
	 * @param password
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] src, String password) throws Exception {
		// DES算法要求有一个可信任的随机数源
		SecureRandom random = new SecureRandom();
		// 创建一个DESKeySpec对象
		DESKeySpec desKey = new DESKeySpec(password.getBytes());
		// 创建一个密匙工厂
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		// 将DESKeySpec对象转换成SecretKey对象
		SecretKey securekey = keyFactory.generateSecret(desKey);
		// Cipher对象实际完成解密操作
		Cipher cipher = Cipher.getInstance("DES");
		// 用密匙初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, securekey, random);
		// 真正开始解密操作
		return cipher.doFinal(src);
	}
	
	public static void main(String[] args) {
//		// 待加密内容
//		String str = "this is an example";
//		// 密码，长度要是8的倍数
//		String password = "Secret Passphrase";
//		byte[] result = encrypt(str.getBytes(), password);
//		System.out.println("加密后内容为 Hex：" + parseByte2HexStr(result));
//		System.out.println("加密后内容为 Base64：" + Crypto.Utils.byteArrayToBase64String(result));
//
//		// 直接将如上内容解密
//		try {
//			byte[] decryResult = decrypt(parseHexStr2Byte(parseByte2HexStr(result)), password);
//			System.out.println("解密后内容为：" + new String(decryResult));
//		} catch (Exception e1) {
//			e1.printStackTrace();
//		}
		
		 String data = "Test String";
         String key = "1234567812345678";
         String iv = "12345678";
		try {
			String encrypted = encrypt(data, key, iv);
			System.out.println(encrypted);
			System.out.println(decrypt(encrypted, key, iv));
//			test();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public static String encrypt(String data, String key, String iv) throws Exception {
		Security.addProvider(new BouncyCastleProvider());
        try {
            Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding", "BC");
            int blockSize = cipher.getBlockSize();

            byte[] dataBytes = data.getBytes("utf-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }

            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "DESede");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);

            return Crypto.Utils.byteArrayToBase64String(encrypted);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String decrypt(String data, String key, String iv) throws Exception {
    	Security.addProvider(new BouncyCastleProvider());
        try
        {
            byte[] encrypted1 = Crypto.Utils.base64StringToByteArray(data);
            
            Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding", "BC");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "DESede");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
 
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
}
